package com.xzy.d;

import com.xzy.a.UserService;
import com.xzy.c.BeanConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 说明：Spring容器与刷新
 *
 * @author xzy
 * @date 2021/11/30 23:10
 */
public class Main {

    public static void main(String[] args) {
        // method1();
        method2();
    }

    /**
     * 支持刷新与不支持刷新的Spring容器
     */
    private static void method1() {
        // 支持刷新
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beanConfig.xml");
        classPathXmlApplicationContext.refresh();

        // 不支持刷新
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        annotationConfigApplicationContext.refresh();

        /*
         * 比较两个类的继承体系：
         *     ClassPathXmlApplicationContext        -> (...) -> AbstractRefreshableApplicationContext -> (...) -> AbstractApplicationContext
         *     AnnotationConfigApplicationContext    -> GenericApplication                                      -> AbstractApplicationContext
         *
         * 查看源码可以发现：
         *     1. refresh() 定义于 AbstractApplicationContext
         *     2. refresh() 调用 refreshBeanFactory() 来刷新 Spring 容器
         *     3. refreshBeanFactory() 是一个抽象方法，交由子类实现
         *     4. GenericApplication 在 refreshBeanFactory() 中禁用了刷新功能；AbstractRefreshableApplicationContext 在 refreshBeanFactory() 中支持了刷新功能
         */
    }

    /**
     * Spring容器支持刷新会有什么用处？
     */
    private static void method2() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beanConfig.xml");

        // 可以观察到刷新后从Spring容器中获取到的单例Bean变了（底层原理：单例池被重新创建）
        System.out.println(applicationContext.getBean(UserService.class));
        System.out.println(applicationContext.getBean(UserService.class));
        System.out.println(applicationContext.getBean(UserService.class));
        applicationContext.refresh();
        System.out.println(applicationContext.getBean(UserService.class));
        System.out.println(applicationContext.getBean(UserService.class));
        System.out.println(applicationContext.getBean(UserService.class));

        /*
         * 更高级一些的功能：在程序的运行过程中，修改XML文件中的Bean定义，然后刷新Spring容器...
         */
    }
}
